package com.chuangjiangx.member.basic.ddd.query;

import com.chuangjiangx.commons.CJBeanUtils;
import com.chuangjiangx.commons.exception.BaseException;
import com.chuangjiangx.commons.page.PagingResult;
import com.chuangjiangx.domain.shared.model.PayEntry;
import com.chuangjiangx.domain.shared.model.PayType;
import com.chuangjiangx.domain.shared.model.Sex;
import com.chuangjiangx.member.basic.dao.model.*;
import com.chuangjiangx.member.basic.ddd.dal.dto.*;
import com.chuangjiangx.member.basic.ddd.query.condition.*;
import com.chuangjiangx.member.basic.ddd.query.dto.MemberDTO;
import com.chuangjiangx.member.basic.ddd.query.dto.MemberDetailDTO;
import com.chuangjiangx.member.basic.ddd.query.dto.MemberDetailForMerchantDTO;
import com.chuangjiangx.member.basic.ddd.query.dto.MemberListDTO;
import com.chuangjiangx.member.basic.dao.mapper.InMbrConfigMapper;
import com.chuangjiangx.member.coupon.ddd.dal.mapper.MbrCouponDalMapper;
import com.chuangjiangx.member.basic.ddd.dal.mapper.MemberDalMapper;
import com.chuangjiangx.member.score.ddd.dal.dto.MemberScoreGift;
import com.chuangjiangx.member.score.ddd.dal.mapper.ScoreStreamDalMapper;
import com.chuangjiangx.member.score.ddd.dal.condition.MemberScoreGiftCondition;
import com.chuangjiangx.member.stored.ddd.dal.mapper.StoredStreamDalMapper;
import com.chuangjiangx.member.basic.dao.mapper.InMbrUserMappingMapper;
import com.chuangjiangx.member.basic.dao.mapper.InMemberMapper;
import com.chuangjiangx.member.coupon.ddd.domain.model.VerifyStatus;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrSourceTerminal;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserMappingType;
import com.chuangjiangx.member.score.ddd.query.dto.CountByMerchantIdAndMemberIdDTO;
import com.chuangjiangx.member.score.ddd.query.dto.MemberScoreDTO;
import com.chuangjiangx.member.score.ddd.query.dto.MemberScoreGiftDTO;
import com.chuangjiangx.member.stored.ddd.query.dto.MemberStoredDTO;
import com.chuangjiangx.member.stored.ddd.query.dto.StoreNameForListDTO;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
public class MemberQuery {

    private Logger logger = LoggerFactory.getLogger(MemberQuery.class);

    @Autowired
    private MemberDalMapper memberDalMapper;
    @Autowired
    private InMemberMapper inMemberMapper;
    @Autowired
    private InMbrConfigMapper inMbrConfigMapper;
    @Autowired
    private InMbrUserMappingMapper inMbrUserMappingMapper;
    @Autowired
    private MbrCouponDalMapper mbrCouponDalMapper;

    @Autowired
    private ScoreStreamDalMapper scoreStreamDalMapper;

    @Autowired
    private StoredStreamDalMapper storedStreamDalMapper;

    /**
     * 查询会员列表
     *
     * @param condition 查询条件
     * @return 返回查询的分页结果
     */
    public PagingResult<MemberListDTO> queryMemberList(MemberCondition condition) {

        Assert.notNull(condition.getMerchantId(), "商户id不能为空！");
        RowBounds rowBounds = new RowBounds(condition.offset(), condition.limit());
        Integer memberListCount = memberDalMapper.countMemberList(condition);
        List<MemberList> list = memberDalMapper.queryMemberList(condition, rowBounds);
        PageInfo<MemberList> pageInfo = new PageInfo<>(list);

        List<MemberListDTO> memberDTOList = new ArrayList<>();
        list.stream().filter(memberForList -> memberForList.getId() != null).forEach(memberForList -> {
            MemberListDTO memberListDTO = new MemberListDTO();
            memberListDTO.setId(memberForList.getId());
            memberListDTO.setMemberCardNum(memberForList.getMemberCardNum());
            memberListDTO.setName(memberForList.getName());
            memberListDTO.setMobile(memberForList.getMobile());
            memberListDTO.setAvailableBalance(memberForList.getAvailableBalance());
            memberListDTO.setAvailableScore(memberForList.getAvailableScore());
            memberListDTO.setLatestStoredDate(memberForList.getLastConsumeTime());
            memberListDTO.setHeadImgUrl(memberForList.getHeadImgUrl());
            memberListDTO.setLastConsumeTime(memberForList.getLastConsumeTime());
            memberDTOList.add(memberListDTO);
        });

        return new PagingResult<>(pageInfo.getPageSize(), pageInfo.getPageNum(),
                memberListCount, memberDTOList);
    }


    /**
     * 查询所有的会员
     *
     * @param merchantId
     * @return
     */
    public List<MemberListDTO> queryMemberListAll(Long merchantId) {

        List<MemberList> list = memberDalMapper.queryMemberListAll(merchantId);

        List<MemberListDTO> memberDTOList = new ArrayList<>();

        list.forEach(memberForList -> {
            MemberListDTO memberListDTO = new MemberListDTO();

            int hisStoredCount = storedStreamDalMapper.queryMemberHisStoredCount(merchantId, memberForList.getId());
            List<MemberHisStored> memberHisStoreds = storedStreamDalMapper.queryMemberHisStored(merchantId, memberForList.getId());
            BigDecimal storedTotal = new BigDecimal("0");
            for (MemberHisStored memberHisStored : memberHisStoreds) {
                if (memberHisStored.getTransactionAmount() != null) {
                    storedTotal = memberHisStored.getTransactionAmount().add(storedTotal);
                }
            }

            memberListDTO.setId(memberForList.getId());
            memberListDTO.setMemberCardNum(memberForList.getMemberCardNum());
            memberListDTO.setName(memberForList.getName());
            memberListDTO.setMobile(memberForList.getMobile());
            memberListDTO.setAvailableBalance(memberForList.getAvailableBalance());
            memberListDTO.setAvailableScore(memberForList.getAvailableScore());
            memberListDTO.setStoredTotal(storedTotal);

            if (memberHisStoreds != null && !memberHisStoreds.isEmpty()) {
                memberListDTO.setLatestStoredDate(memberHisStoreds.get(0).getDateTime());
            } else {
                memberListDTO.setLatestStoredDate(null);
            }

            memberListDTO.setHisStoredCount(hisStoredCount);

            memberDTOList.add(memberListDTO);
        });
        return memberDTOList;
    }


    /**
     * 根据会员id查询交易积分记录
     */
    public PagingResult<MemberScoreGiftDTO> queryMemberScoreGiftList(MemberScoreGiftCondition condition) {
        Assert.notNull(condition.getMerchantId(), "商户id不能为空");
        RowBounds rowBounds = new RowBounds(condition.offset(), condition.limit());
        List<MemberScoreGift> list = memberDalMapper.queryMemberScoreGift(condition, rowBounds);
        PageInfo<MemberScoreGift> pageInfo = new PageInfo<>(list);
        List<MemberScoreGiftDTO> memberScoreGiftDTOS = CJBeanUtils.convertCollection(list, MemberScoreGiftDTO.class);
        return new PagingResult<>(pageInfo.getPageSize(), pageInfo.getPageNum(),
                pageInfo.getTotal(), memberScoreGiftDTOS);

    }

    /**
     * 根据id查询会员详情--商户平台
     */
    public MemberDetailForMerchantDTO queryMemberDetailById(QueryMemberInfoCondition condition) {
        MemberDetailForMerchant memberDetail = memberDalMapper.queryMemberDetailById(condition);
        MemberDetailForMerchantDTO memberDetailDTO = new MemberDetailForMerchantDTO();
        CJBeanUtils.convertBean(memberDetail, memberDetailDTO, (source, target) -> {
            if (source.getSex() != null) {
                target.setSexText(Sex.getSex(source.getSex()).name);
            }
            if (source.getRegisterTerminalType() != null) {
                target.setRegisterTerminalTypeText(MbrSourceTerminal.getSourceTerminal(source.getRegisterTerminalType()).name);
            }
        });
        return memberDetailDTO;
    }

    /**
     * 根据手机号码查询会员信息--客户端(后期废弃)
     */
    public MemberDetailDTO searchMemberDetailByMobile(SearchMemberInfoCondition searchMemberInfoCondition) {
        MemberDetail memberDetail = memberDalMapper.searchMemberDetailByMobile(searchMemberInfoCondition);
        if (memberDetail == null) {
            return null;
        } else {
            MemberDetailDTO memberDetailDTO = new MemberDetailDTO();
            CJBeanUtils.convertBean(memberDetail, memberDetailDTO, (source, target) -> {
                if (source.getSex() != null) {
                    target.setSexText(Sex.getSex(source.getSex()).name);
                }
                if (source.getRegisterTerminalType() != null) {
                    target.setRegisterTerminalTypeText(MbrSourceTerminal.getSourceTerminal(source.getRegisterTerminalType()).name);
                }
            });
            return memberDetailDTO;
        }
    }

    /**
     * 根据会员id查询会员信息
     *
     * @return
     */
    public MemberDetailDTO searchMemberDetailById(Long memberId) {
        MemberDetail memberDetail = memberDalMapper.searchMemberDetailById(memberId);
        if (memberDetail == null) {
            return null;
        } else {
            MemberDetailDTO memberDetailDTO = new MemberDetailDTO();
            //会员拥有卡券中可用数量
            Integer usableCoupons = mbrCouponDalMapper.countMbrHasCoupons(memberId,VerifyStatus.UNUSED.code);
            memberDetailDTO.setAvailableCouponAmount(usableCoupons);
            CJBeanUtils.convertBean(memberDetail, memberDetailDTO, (source, target) -> {
                if (source.getSex() != null) {
                    target.setSexText(Sex.getSex(source.getSex()).name);
                }
                if (source.getRegisterStoreName() == null || source.getRegisterStoreName().equals("")) {
                    target.setRegisterStoreName("H5");
                }
                if (source.getRegisterTerminalType() != null) {
                    target.setRegisterTerminalTypeText(MbrSourceTerminal.getSourceTerminal(source.getRegisterTerminalType()).name);
                }
            });
            return memberDetailDTO;
        }
    }

    /**
     * 根据会员人脸id查询会员信息
     *
     * @return
     */
    public MemberDetailDTO searchMemberDetailByFaceId(String faceId) {
        MemberDetail memberDetail = memberDalMapper.searchMemberDetailByFaceId(faceId);
        if (memberDetail == null) {
            return null;
        } else {
            MemberDetailDTO memberDetailDTO = new MemberDetailDTO();
            //会员拥有卡券中可用数量
            Integer usableCoupons = mbrCouponDalMapper.countMbrHasCoupons(memberDetail.getMemberId(),VerifyStatus.UNUSED.code);
            memberDetailDTO.setAvailableCouponAmount(usableCoupons);
            CJBeanUtils.convertBean(memberDetail, memberDetailDTO, (source, target) -> {
                if (source.getSex() != null) {
                    target.setSexText(Sex.getSex(source.getSex()).name);
                }
            });
            return memberDetailDTO;
        }
    }

    /**
     * 查询会员当前积分、历史累计积分、历史消耗积分
     *
     * @param condition
     * @return MemberAccount
     */
    public CountByMerchantIdAndMemberIdDTO queryCountByMerchantIdAndMemberId(QueryMemberAccountCondition condition) {
        MemberAccount memberAccount = memberDalMapper.queryMemberAccount(condition);
        CountByMerchantIdAndMemberIdDTO countByMerchantIdAndMemberIdDTO = new CountByMerchantIdAndMemberIdDTO();
        if (memberAccount == null) {
            return null;
        } else {
            BeanUtils.copyProperties(memberAccount, countByMerchantIdAndMemberIdDTO);
            return countByMerchantIdAndMemberIdDTO;
        }
    }

    /**
     * 查询所有的门店以及模糊查询
     */
    public List<StoreNameForListDTO> queryAllStoreName(String storeName, Long merchantId) {
        if (storeName != null) {
            storeName = "%" + storeName + "%";
        }
        List<StoreNameForList> storeNameForLists = memberDalMapper.queryAllStoreName(storeName, merchantId);
        List<StoreNameForListDTO> storeNameForListDTOS = CJBeanUtils.convertCollection(storeNameForLists, StoreNameForListDTO.class);
        return storeNameForListDTOS;
    }

    /**
     * 查询会员可用积分，历史累计积分-客户端，商户平台
     *
     * @param memberScoreCondition
     * @return
     */
    public MemberScoreDTO queryMemberScoreForClient(QueryMemberAccountCondition memberScoreCondition) {
        Assert.notNull(memberScoreCondition.getMemberId(), "会员id不能为空");
        Assert.notNull(memberScoreCondition.getMerchantId(), "商户id不能为空");
        MemberAccount memberAccount = memberDalMapper.queryMemberAccount(memberScoreCondition);
        MemberScoreDTO memberScoreDTO = new MemberScoreDTO();
        memberScoreDTO.setAvailableScore(memberAccount == null ? 0L : memberAccount.getAvailableScore());
        memberScoreDTO.setTotalScore(memberAccount == null ? 0L : memberAccount.getTotalScore());
        return memberScoreDTO;
    }

    /**
     * 查询会员可用余额，历史储值金额-客户端，商户平台
     *
     * @param memberStoredCondition
     * @return
     */
    public MemberStoredDTO queryMemberStoredForClient(QueryMemberAccountCondition memberStoredCondition) {
        Assert.notNull(memberStoredCondition.getMemberId(), "会员id不能为空");
        Assert.notNull(memberStoredCondition.getMerchantId(), "商户id不能为空");
        MemberAccount memberAccount = memberDalMapper.queryMemberAccount(memberStoredCondition);
        MemberStoredDTO memberStoredDTO = new MemberStoredDTO();
        memberStoredDTO.setAvailableBalance(memberAccount == null ? new BigDecimal(0.00) : memberAccount.getAvailableBalance());
        memberStoredDTO.setTotalRechargeBalance(memberAccount == null ? new BigDecimal(0.00) : memberAccount.getTotalRechargeBalance().add(memberAccount.getTotalGiveBalance()));
        return memberStoredDTO;
    }

    /**
     * 根据商户Id type openid 查询会员
     *
     * @param condition
     * @return
     */
    public MemberDTO queryByMbrUserMapingCondition(MbrUserMapingCondition condition) {
        InMbrUserMappingExample example = new InMbrUserMappingExample();
        InMbrUserMappingExample.Criteria criteria = example.createCriteria();
        criteria.andTypeEqualTo(condition.getType());

        if (condition.getMerchantId() != null) {
            criteria.andMerchantIdEqualTo(condition.getMerchantId());
        }
        if(StringUtils.isNotBlank(condition.getOpenId())){
            criteria.andOpenIdEqualTo(condition.getOpenId());
        }
        if(StringUtils.isNotBlank(condition.getMopenId())){
            criteria.andMopenIdEqualTo(condition.getMopenId());
        }
        if(condition.getMemberId() != null){
            criteria.andMemberIdEqualTo(condition.getMemberId());
        }
        List<InMbrUserMapping> inMbrUserMappings = inMbrUserMappingMapper.selectByExample(example);
        if (inMbrUserMappings.isEmpty()) {
            return null;
        }

        InMbrUserMapping inMbrUserMapping = inMbrUserMappings.get(0);
        InMember inMember = inMemberMapper.selectByPrimaryKey(inMbrUserMapping.getMemberId());
        if (inMember == null) {
            return null;
        }
        MemberDTO dto = new MemberDTO();
        BeanUtils.copyProperties(inMember, dto);
        dto.setOpenid(inMbrUserMapping.getOpenId());
        dto.setMopenid(inMbrUserMapping.getMopenId());
        return dto;
    }

    /**
     * 根据商户Id 和 手机号 查询会员
     *
     * @param merchantId
     * @param mobile
     * @return
     */
    public MemberDTO queryByMerchantAndMobile(Long merchantId, String mobile) {
        InMemberExample example = new InMemberExample();
        example.createCriteria()
                .andMerchantIdEqualTo(merchantId)
                .andMobileEqualTo(mobile);
        List<InMember> inMembers = inMemberMapper.selectByExample(example);
        if (inMembers.isEmpty()) {
            return null;
        }
        MemberDTO dto = new MemberDTO();
        BeanUtils.copyProperties(inMembers.get(0), dto);
        return dto;
    }

    /**
     * 根据会有ID查询 会员
     *
     * @param memberId
     * @return
     */
    public MemberDTO queryByMemberId(Long memberId) {

        InMember inMember = inMemberMapper.selectByPrimaryKey(memberId);
        if (null == inMember) {
            return null;
        }
        MemberDTO dto = new MemberDTO();
        BeanUtils.copyProperties(inMember, dto);
        return dto;
    }

    /**
     * 根据会员卡号查询会员信息
     * @param cardNO
     * @return
     */
    public MemberDTO queryByCardNO(String cardNO) {
        InMemberExample example = new InMemberExample();
        example.createCriteria()
                .andMemberCardNumEqualTo(cardNO);
        List<InMember> inMembers = inMemberMapper.selectByExample(example);
        if(inMembers.isEmpty()){
            return null;
        }
        MemberDTO dto = new MemberDTO();
        BeanUtils.copyProperties(inMembers.get(0), dto);
        InMbrUserMappingExample ie = new InMbrUserMappingExample();
        ie.createCriteria()
                .andMerchantIdEqualTo(dto.getMerchantId())
                .andMemberIdEqualTo(dto.getId());
        List<InMbrUserMapping> inMbrUserMappings = inMbrUserMappingMapper.selectByExample(ie);
        if(!inMbrUserMappings.isEmpty()){
            inMbrUserMappings.stream()
                    .forEach(e -> {
                        MbrUserMappingType type = MbrUserMappingType.fromValue(e.getType());
                        switch (type){
                            case ALIPAY:
                                break;
                            case WX:
                                dto.setOpenid(e.getOpenId());
                                dto.setMopenid(e.getMopenId());
                                break;
                            default:
                                break;
                        }
                    });
        }
        return dto;
    }


    /**
     * 判断商户是否能够使用会员二期
     * @param merchantId
     * @return
     */
    public Boolean isCanUseMember2(Long merchantId){
        return memberDalMapper.isCanUseMember2(merchantId);
    }

    /**
     * 查询商户是否能够使用H5C扫B支付+核销
     * @param merchantId
     * @return
     */
    public Boolean isCanUserH5ctob(Long merchantId){
        boolean is = memberDalMapper.isOpenMember2(merchantId);
        if(!is){
            return false;
        }
        /*
          支付渠道
          1-微信服务商
          4-支付宝服务商
          13-拉卡拉聚合
         */
        Integer wx = memberDalMapper.queryConfigPayChannelId(merchantId, PayType.MICRO_PAY.value, PayEntry.WXPAY.value);
        if(wx != null){
            is = (1 == wx || 13 == wx);
            if(!is){
                log.info("商户ID:{},微信支付配置的渠道ID是:{},无法进入H5C扫B支付+核销",merchantId,wx);
                return false;
            }
        }

        Integer ali = memberDalMapper.queryConfigPayChannelId(merchantId, PayType.MICRO_PAY.value, PayEntry.ALIPAY.value);
        if(ali != null){
            is =  (4 == ali || 13 == ali);
            if(!is){
                log.info("商户ID:{},支付宝支付配置的渠道ID是:{},无法进入H5C扫B支付+核销",merchantId,ali);
                return false;
            }
        }
        return true;
    }

    /**
     * 判断会员能否同步微信卡包
     * @param canSyncWxCondition
     * 0 - 不可以  1- 可以  2- 已经同步
     */
    public int canSyncWx(CanSyncWxCondition canSyncWxCondition){
        long memberId = canSyncWxCondition.getMemberId().getId();
        long merchantId = canSyncWxCondition.getMerchantId().getId();
        InMember inMember = inMemberMapper.selectByPrimaryKey(memberId);
        if (inMember == null){
            throw new BaseException("","会员不存在!" + memberId);
        }
        if(1 == inMember.getSyncWxStatus()){
            return 2;
        }

        InMbrConfigExample inMbrConfigExample = new InMbrConfigExample();
        inMbrConfigExample.createCriteria()
                .andMerchantIdEqualTo(merchantId);
        List<InMbrConfig> inMbrConfigs = inMbrConfigMapper.selectByExample(inMbrConfigExample);
        if (!inMbrConfigs.isEmpty()){
            InMbrConfig inMbrConfig=inMbrConfigs.get(0);
            if(1 == inMbrConfig.getWxSyncSwitch()){
                return 1;
            }
        }
        return 0;
//       if(!Integer.valueOf(1).equals(inMbrConfig.getWxSyncSwitch())){
//            throw new BaseException("","未开启同步至微信卡包功能");
//       }
//       if(!Integer.valueOf(0).equals(inMember.getSyncWxStatus())){
//           throw new BaseException("","已领取微信会员卡");
//        }
    }

    public List<InMember> getMemberDTOByLastPhoneNumber(String lastPhoneNumber, Long merchantId) {
        InMemberExample example = new InMemberExample();
        example.createCriteria().andMobileLike("%" + lastPhoneNumber).andMerchantIdEqualTo(merchantId);
        List<InMember> members = inMemberMapper.selectByExample(example);
        return members;
    }

}
